package org.tinygroup.signature;

import java.io.StringWriter;

import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.tinygroup.logger.LogLevel;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class CheckChannelInterceptor extends AbstractSignChannelInterceptor {

	@Override
	protected String internalProcessor(Element element) throws Exception {
		// 查找签名元素
		NodeList nl = element.getElementsByTagNameNS(XMLSignature.XMLNS,
				"Signature");
		if (nl.getLength() == 0) {
			throw new Exception("没有找到<Signature>元素");
		}
		LOGGER.logMessage(LogLevel.DEBUG, "找到<Signature>元素.");
		Node signatureNode = nl.item(0);
		XMLSignature signature = xmlSignatureFactory
				.unmarshalXMLSignature(new DOMStructure(signatureNode));
		DOMValidateContext valCtx = new DOMValidateContext(keyPair.getPublic(),
				signatureNode);
		boolean pass = signature.validate(valCtx);
		if (!pass) {
			return null;
		}
		element.removeChild(signatureNode);
		return toStringFromDoc(element);
	}

	/*
	 * 把dom文件转换为xml字符串
	 */
	public static String toStringFromDoc(Element element) throws Exception {
		String result = null;
		if (element != null) {
			StringWriter strWtr = new StringWriter();
			try {
				StreamResult strResult = new StreamResult(strWtr);
				TransformerFactory tfac = TransformerFactory.newInstance();
				javax.xml.transform.Transformer t = tfac.newTransformer();
				t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
				t.setOutputProperty(OutputKeys.INDENT, "yes");
				t.setOutputProperty(OutputKeys.METHOD, "xml"); // xml, html,
				// text
				t.setOutputProperty(
						"{http://xml.apache.org/xslt}indent-amount", "4");
				t.transform(new DOMSource(element),
						strResult);
				result = strResult.getWriter().toString();
			} finally {
				strWtr.close();
			}

		}
		return result;
	}

}
